/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - core\system\io\stream
// Copyright (c) 2014.  All Rights Reserved
//
// File:		AEIFileStreamInput.h
// Author:		Gianluca Belardelli
// Date:		25/02/2014
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AEIFILESTREAMINPUT_H_
#define _AEIFILESTREAMINPUT_H_

/// \brief
/// Classe base per tutti gli stream di tipo input.
class AEIFileStreamInput
{
// Members
protected:
	AEBOOL32			m_bEOF;
	AEUINT32			m_uiLookupHash;
	AEIFileStreamManager *m_lpParentMgr;

	VString m_sMetaData;
	VString m_sInitialDataDir;

// Methods
public:
	/// \brief
	///   The object must be constructed by a AEIFileStreamManager, which will pass itself as the parent manager to the instance.
	AE_FORCEINLINE AEIFileStreamInput( AEIFileStreamManager *lpManager );
	
	/// \brief
	///   Destructor
	virtual ~AEIFileStreamInput( void ) {}
	
	/// \brief
	/// Ritorna un puntatore all'oggetto di tipo AEIFileStreamManager che ha creato lo stream.
	AE_FORCEINLINE AEIFileStreamManager *GetManager( void ) const;
	
	/// \brief
	///   This function closes the stream and deallocates its data. The object can not be used anymore after this call.
	virtual void Close( void ) = 0;
	
	/// \brief
	///   Reads up to iLen number of bytes to pBuffer. Returns the exact number of bytes that was read (may be smaller than iLen).
	/// 
	/// \param pBuffer
	///   The destination buffer.
	/// 
	/// \param iLen
	///   Number of bytes to read.
	/// 
	/// \return
	///   size_t iRead : Number of actual bytes read.
	virtual AEINT32 Read( void *lpBuffer, AEINT32 nLen ) = 0;
	
	/// \brief
	///   Read function that performs endianess conversion on the read buffer.
	/// 
	/// This version of the read function calls the virtual Read function and performs the conversion
	/// on the read block.
	/// 
	/// The expected format is passed in the format string.
	/// 
	/// Each character in the format string represents a data type: i=int, s=short, c=char, f=float, q=quad word (8bytes)
	/// For full documentation of the format string see the EndianSwitchWorker() documentation.
	/// 
	/// \param pBuffer
	///   The destination buffer.
	/// 
	/// \param iLen
	///   Length of the buffer in bytes, must be large enough to hold the data that the format string specifies (ie. if "f" is used to read a float, the buffer must be at least 4 bytes large).
	/// 
	/// \param pFormat
	///   Format specification, see EndianSwitchWorker() for more details.
	/// 
	/// \param iRepetitions
	///   Number of repetitions of the format string.
	/// 
	/// \return
	///   size_t iRead : Number of actual bytes read.
	/// 
	/// \example
	///   Reads two integers into a structure:
	///   \code
	///   pFile->Read(&header, sizeof(header),"ii", 1);
	///   \endcode
	AEINT32 Read( void *lpBuffer, AEINT32 nLen, const char *lpFormat, AEUINT32 uiRepetitions = 1 );
	
	
	/// \brief
	///   Sets the byte position where to read/write the file. This function will be removed in the future.
	/// 
	/// \param iPos
	///   Position relative to base position (iMode)
	/// 
	/// \param iMode
	///   Base position. Must be VFS_SETPOS_SET, VFS_SETPOS_CURRENT or VFS_SETPOS_END (from the VFilePositionMode enum).
	virtual AEBOOL32 SetPos( AELONG lPos, AEINT32 nMode ) = 0;
	
	/// \brief
	///   Returns the current file posistion. This function will be removed in the future.
	virtual AELONG GetPos( void ) = 0;
	
	/// \brief
	///   Returns the size of the file in bytes.
	virtual AELONG GetSize( void ) = 0;
	
	/// \brief
	///   Returns the name of the file.
	virtual const char *GetFileName( void ) = 0;
	
	/// \brief
	///   Indicates whether the end of file has been reached.
	AE_FORCEINLINE AEBOOL32 IsEOF( void );
	
	/// \brief
	///  Returns the modification date of the file the stream points to.
	virtual AEBOOL32 GetTimeStamp( AEFileTime &ftResult );
	
	/// \brief
	///   Sets the data directory in which the asset for this stream was first successfully looked up.
	/// \param szDataDir
	///   The data directory to set.
	void SetInitialDataDir( const char *lpDataDir );
	
	/// \brief
	///   Gets the data directory in which the asset for this stream was first
	///   successfully looked up. If the stream was not opened as the result of 
	///   an asset look-up, this function returns \c NULL.
	/// \return
	///   The initial data directory, or \c NULL if this stream was not opened as a result of an asset look-up.
	AE_FORCEINLINE const char *GetInitialDataDir( void ) const;
	
	/// \brief
	///   Sets the metadata string to go with this stream.
	/// \param szMetadata
	///   The metadata string. Can be NULL.
	void SetMetadata( const char *lpMetadata );
	
	/// \brief
	///   Returns the metadata string set for this stream.
	/// \return
	///   The metadata set for this stream. May be NULL.
	AE_FORCEINLINE const char *GetMetadata( void ) const;
	
	/// \brief
	///   Sets the hash of the asset lookup entry that identified the underlying file in the relevant asset lookup table.
	/// \param uiHash
	///   the hash value to set
	AE_FORCEINLINE void SetLookupHash( AEUINT32 uiHash );
	
	/// \brief
	///   Returns the hash of the asset lookup entry that identified the underlying file in the relevant asset lookup table.
	/// \return
	///   the hash value (0 if not explicitly set)
	AEUINT32 GetLookupHash( void ) const;
};

#include "AEIFileStreamInput.inl"

#endif // _AEIFILESTREAMINPUT_H_
